/**
 * Created by no1 on 2015/7/24.
 */

'use strict';
let mongoDao = require('./mongoDao/RoleDao.js');
let permissionDispatcher = require('./permission.js');

function RoleDispatcher() {
    this.updatedAt = null;
    this.pCache = {}; // { roleName : permissonJson }
    //{
    //    "管理员":[
    //          "商家管理:添加商家",
    //          "商家管理:编辑商家",
    //          "商家详情:商家详情"
    //    ],
    //    "商户":[
    //        "商家管理:添加商家",
    //        "商家详情:商家详情"
    //    ],
    //}
}
module.exports = new RoleDispatcher();

let rp = RoleDispatcher.prototype;

/**
 * 增加角色,如果该角色已经存在,则会覆盖
 {
     "roleName": "管理员",
     "permission":{
        "商家管理": ["添加商家","编辑商家"],
        "商家详情": ["商家详情"]
     }
 }
 * @param inParams
 * @returns {*}
 */
rp.add = function*(inParams) {
    // add to mongo first
    let roleName = inParams.roleName;

    // check permission exists
    let p = inParams.permission;
    let checkResult = yield permissionDispatcher.checkPermissionExists(p);
    if (checkResult.error) {
        return checkResult;
    }

    // 组装
    let arr = [];
    for (var gName in p) {
        let group = p[gName];
        group.forEach(function (name) {
            let uName = permissionDispatcher.getUniqueName(gName, name);
            arr.push(uName);
        })
    }

    let roleJson = {roleName: roleName, pUniqueName: arr};
    let result = yield mongoDao.saveOne(roleJson);

    // rebuild cache
    yield this.refreshCache(roleName);

    return result;
};

/**
 * 获取角色的权限图
 * @returns {null|*|result}
 {
   "roleName": "管理员"
 }
 */
rp.permissions = function*(inParams) {
    let rName = inParams.roleName;
    if (!this.pCache[rName]) {
        yield this.refreshCache(rName);
    }

    let p = this.pCache[rName];
    if (!p) {
        return {error: '不存在的角色'};
    }
    // [ "商家管理:添加商家", "商家管理:编辑商家", "商家详情:商家详情" ]
    let all = yield permissionDispatcher.getAll();
    //{ "商家管理": ["添加商家","编辑商家"] }

    // 进行组装
    let ret = {};
    for (let gName in all) {
        let group = all[gName];
        let list = [];
        group.forEach(function (name) {
            let uName = permissionDispatcher.getUniqueName(gName, name);
            let obj = {};
            obj[name] = 0; //default;
            if (p.indexOf(uName) >= 0) {
                obj[name] = 1;
            }
            list.push(obj);
        });
        ret[gName] = list;
    }

    return ret;
};

/**
 * refresh cache
 */
rp.refreshCache = function*(roleName) {
    this.pCache[roleName] = null;
    let roleInfo = yield mongoDao.get({name: roleName});
    if (roleInfo === null) { // 不存在的角色
        return;
    }
    this.pCache[roleName] = roleInfo.pUniqueName;
};

/**
 * 判断roleName是否存在
 * @param roleName
 */
rp.hasRole = function*(roleName) {
    if (!this.pCache[roleName]) {
        yield this.refreshCache(roleName);
    }
    let p = this.pCache[roleName];
    if (!p) {
        return {error: '不存在的角色'};
    } else {
        return {errCode: 0};
    }
};

/**
 * 检测权限是否存在
 {
  "roleName": "管理员",
  "groupName": "商家管理",
  "permissionName": "添加商家"
 }
 */
rp.checkPermission = function*(inParams) {
    let rName = inParams.roleName;
    let gName = inParams.groupName;
    let pName = inParams.permissionName;

    let exists = yield permissionDispatcher.exists(gName, pName);
    if (exists.error) {
        return exists;
    }

    if (!this.pCache[rName]) {
        yield this.refreshCache(rName);
    }

    let permissions = this.pCache[rName];
    if (!permissions) {
        return {hasPermission: false};
    }

    let uName = permissionDispatcher.getUniqueName(gName, pName);
    if (permissions.indexOf(uName) < 0) {
        return {hasPermission: false};
    }
    return {hasPermission: true};
};

/**
 *  {
     "roleName": "管理员",
     "permissions": [
         {"商家管理": ["添加商家","编辑商家"]},
         {"商家管理": ["添加商家","编辑商家"]}
     ]
 }
 * @param inParams
 */
rp.checkMany = function*(inParams) {
    let roleName = inParams.roleName;
    let list = [];
    inParams.permissions.forEach(function (item) {
        let gName = Object.keys(item)[0];
        let group = item[gName];
        group.forEach(function (p) {
            list.push({
                "roleName": roleName,
                "groupName": gName,
                "permissionName": p
            });
        })
    });

    let self = this;
    for (let i = 0; i < list.length; i++) {
        let has = yield self.checkPermission(list[i]);
        if (has.error) {
            return has;
        }
        if (!has.hasPermission) {
            return {
                hasPermission: false,
                deny: list[i].groupName + ":" + list[i].permissionName
            };
        }
    }
    return {hasPermission: true};
};